package top.fullj.fsm;

import com.google.common.base.Preconditions;
import top.fullj.func.Action;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author bruce.wu
 * @since 2021/8/2 10:38
 */
public class StateMachine {

    private volatile State current;

    private final Map<Condition, State> graph = new HashMap<>();

    public StateMachine(State init, List<Transaction> transactions) {
        Preconditions.checkNotNull(init);
        this.current = init;
        for (Transaction transaction : transactions) {
            graph.put(transaction.condition, transaction.next);
        }
    }

    private State next(Event event) {
        Condition cond = new Condition(current, event);
        return graph.get(cond);
    }

    public State state() {
        return current;
    }

    public boolean is(State state) {
        Preconditions.checkNotNull(state);
        return state.equals(current);
    }

    public void fire(Event event) {
        this.fire(event, null);
    }

    public void fire(Event event, Action action) {
        Preconditions.checkNotNull(event);
        synchronized (this) {
            State next = next(event);
            Preconditions.checkNotNull(next);
            State origin = current;
            origin.leave(this);
            if (action != null) {
                action.accept();
            }
            current = next;
            next.enter(this);
            onStateChanged(origin, current);
        }
    }

    public void onStateChanged(State origin, State state) {}

}
